home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 51 / Amiga Format CD51 (2000-03-10)(Future Publishing)(GB)[!][issue 2000-04].iso / -in_the_mag- / workbench / term_4.8 / extras / source / gtlayout-source.lha / LT_MenuControlTagList.c < prev    next >
C/C++ Source or Header  |  1997-07-08  |  8KB  |  393 lines

  1. /*
  2. **    GadTools layout toolkit
  3. **
  4. **    Copyright © 1993-1997 by Olaf `Olsen' Barthel
  5. **        Freely distributable.
  6. **
  7. **    :ts=4
  8. */
  9.  
  10. #ifndef _GTLAYOUT_GLOBAL_H
  11. #include "gtlayout_global.h"
  12. #endif
  13.  
  14. #include "Assert.h"
  15.  
  16. #ifdef DO_MENUS
  17.  
  18. /****** gtlayout.library/LT_MenuControlTagList ******************************************
  19. *
  20. *   NAME
  21. *    LT_MenuControlTagList -- Manipulate menus, menu/submenu items (V11)
  22. *
  23. *   SYNOPSIS
  24. *    LT_MenuControlTagList(Window,Menu,Tags)
  25. *                           A0   A1     A2
  26. *
  27. *    VOID LT_MenuControlTagList(struct Window *,struct Menu *,struct TagItem *);
  28. *
  29. *    VOID LT_MenuControlTags(struct Window *,struct Menu *,...);
  30. *
  31. *   FUNCTION
  32. *    This routine provides a rather efficient way to set and to clear,
  33. *    to enable and to disable a number of menus, menu/submenu items
  34. *    all at once.
  35. *
  36. *    In v18 this routine was modified to disconnect a menu strip
  37. *    from a window if it is about to change checkmark states. In
  38. *    earlier releases or if a single menu is attached to several
  39. *    windows it is recommended that you disconnect the menu from
  40. *    the windows it is attached to before you call this routine.
  41. *
  42. *    As of v18 this routine is smart enough to handle menu
  43. *    mutual exclusion.
  44. *
  45. *   INPUTS
  46. *    Window - Pointer to Window this menu is attached to. Starting with
  47. *             gtlayout.library v16 this parameter may be NULL.
  48. *
  49. *    Menu - Pointer to Menu structure as returned by LT_NewMenuTagList.
  50. *
  51. *    Tags - Pointer to a list of tagitem values, as found
  52. *           in gtlayout.h
  53. *
  54. *
  55. *    Tags:
  56. *
  57. *    LAMN_ID (ULONG) - Unique ID of menu/menu item/submenu item to
  58. *        manipulate.
  59. *
  60. *    LAMN_Checked (BOOL) - Set the checkmark state of the
  61. *        menu/submenu item.
  62. *
  63. *    LAMN_Disabled (BOOL) - Set the availability state of the
  64. *        menu/menu item/submenu item.
  65. *
  66. *    LAMN_FullMenuNum (UWORD) - Intuition menu number of
  67. *        menu/submenu item to manipulate. You would pass the
  68. *        result of the FULLMENUNUM() macro here for the
  69. *        item in question. (V30)
  70. *
  71. *   RESULT
  72. *    none
  73. *
  74. *   EXAMPLE
  75. *    The following tagitem list will clear the checkmark and
  76. *    disable the menu item associated with ID 5 and set the
  77. *    checkmark for the item associated with ID 6:
  78. *
  79. *        LAMN_ID,         5,
  80. *          LAMN_Checked,  FALSE,
  81. *          LAMN_Disabled, TRUE,
  82. *        LAMN_ID,         6,
  83. *          LAMN_Checked,  TRUE,
  84. *        TAG_DONE
  85. *
  86. *   BUGS
  87. *    In library versions up to and including v17.2 this routine
  88. *    is broken. It won't do any harm, it just doesn't do what you
  89. *    want it to do.
  90. *
  91. *    Up to and including V42.1 the library could fail to find the
  92. *    correct menu items corresponding to the LAMN_ID given. This
  93. *    has been fixed in V43.1.
  94. *
  95. *    Up to and including V43.1 trying to change the attributes
  96. *    of an item with LAMN_ID whose ID number could not be found
  97. *    could lead to a crash. This has been fixed in V43.2.
  98. *
  99. *   SEE ALSO
  100. *    gtlayout.library/LT_NewMenuTagList
  101. *
  102. ******************************************************************************
  103. *
  104. */
  105.  
  106. VOID LIBENT
  107. LT_MenuControlTagList(REG(a0) struct Window *Window,REG(a1) struct Menu *IntuitionMenu,REG(a2) struct TagItem *Tags)
  108. {
  109.     RootMenu *            Root = (RootMenu *)((ULONG)IntuitionMenu - offsetof(RootMenu,Menu));
  110.     struct TagItem *    List;
  111.     struct TagItem *    Entry;
  112.     ULONG                ID;
  113.     MenuNode *            Menu = NULL;
  114.     ItemNode *            Item = NULL;
  115.     BOOL                GotIt;
  116.     BOOL                Disconnected = FALSE;
  117.  
  118.     if(!IntuitionMenu)
  119.         return;
  120.  
  121.     List = Tags;
  122.  
  123.         // Make sure that if window and menu are provided,
  124.         // the menu is attached to the window.
  125.  
  126.     if(Window && IntuitionMenu)
  127.     {
  128.         if(Window->MenuStrip != IntuitionMenu)
  129.             Window = NULL;
  130.     }
  131.  
  132.     while(Entry = NextTagItem(&List))
  133.     {
  134.         switch(Entry->ti_Tag)
  135.         {
  136.                 // We start with a menu/item/subitem ID
  137.  
  138.             case LAMN_ID:
  139.  
  140.                 GotIt = FALSE;
  141.  
  142.                 ID = (ULONG)Entry->ti_Data;
  143.  
  144.                     // Check if it's on the menu list
  145.  
  146.                 for(Menu = (MenuNode *)Root->MenuList.mlh_Head ; Menu->Node.mln_Succ ; Menu = (MenuNode *)Menu->Node.mln_Succ)
  147.                 {
  148.                     if(Menu->ID == ID)
  149.                     {
  150.                         GotIt = TRUE;
  151.  
  152.                         Item = NULL;
  153.  
  154.                         break;
  155.                     }
  156.                 }
  157.  
  158.                     // If it isn't, check the item/subitem list
  159.  
  160.                 if(!GotIt)
  161.                 {
  162.                     for(Item = (ItemNode *)Root->ItemList.mlh_Head ; Item->Node.mln_Succ ; Item = (ItemNode *)Item->Node.mln_Succ)
  163.                     {
  164.                         if(Item->ID == ID)
  165.                         {
  166.                             GotIt = TRUE;
  167.  
  168.                             Menu = NULL;
  169.  
  170.                             break;
  171.                         }
  172.                     }
  173.                 }
  174.  
  175.                     // Do nothing if none is found
  176.  
  177.                 if(!GotIt)
  178.                 {
  179.                     Menu = NULL;
  180.                     Item = NULL;
  181.                 }
  182.  
  183.                 break;
  184.  
  185.                 // We start with a menu/item/subitem ID
  186.  
  187.             case LAMN_FullMenuNum:
  188.  
  189.                 GotIt = FALSE;
  190.  
  191.                 ID = (ULONG)Entry->ti_Data;
  192.  
  193.                     // Check if it's on the menu list
  194.  
  195.                 for(Menu = (MenuNode *)Root->MenuList.mlh_Head ; Menu->Node.mln_Succ ; Menu = (MenuNode *)Menu->Node.mln_Succ)
  196.                 {
  197.                     if(Menu->MenuCode == ID)
  198.                     {
  199.                         GotIt = TRUE;
  200.  
  201.                         Item = NULL;
  202.  
  203.                         break;
  204.                     }
  205.                 }
  206.  
  207.                     // If it isn't, check the item/subitem list
  208.  
  209.                 if(!GotIt)
  210.                 {
  211.                     for(Item = (ItemNode *)Root->ItemList.mlh_Head ; Item->Node.mln_Succ ; Item = (ItemNode *)Item->Node.mln_Succ)
  212.                     {
  213.                         if(Item->MenuCode == ID)
  214.                         {
  215.                             GotIt = TRUE;
  216.  
  217.                             Menu = NULL;
  218.  
  219.                             break;
  220.                         }
  221.                     }
  222.                 }
  223.  
  224.                     // Do nothing if none is found
  225.  
  226.                 if(!GotIt)
  227.                 {
  228.                     Menu = NULL;
  229.                     Item = NULL;
  230.                 }
  231.  
  232.                 break;
  233.  
  234.                 // Fiddle with the checkmark
  235.  
  236.             case LAMN_Checked:
  237.  
  238.                 if(Item)
  239.                 {
  240.                         // Disconnect the window menu before we
  241.                         // change the states
  242.  
  243.                     if(Window && !Disconnected)
  244.                     {
  245.                         ClearMenuStrip(Window);
  246.  
  247.                         Disconnected = TRUE;
  248.                     }
  249.  
  250.                     if(Entry->ti_Data)
  251.                         Item->Item.Flags |=  CHECKED;
  252.                     else
  253.                         Item->Item.Flags &= ~CHECKED;
  254.  
  255.                         // Now check for mutual exclusion
  256.  
  257.                     if(Item->Item.MutualExclude && Entry->ti_Data)
  258.                     {
  259.                         ItemNode    *Node;
  260.                         ULONG         Exclude;
  261.                         LONG         Result;
  262.                         BOOL         IsSub;
  263.  
  264.                         Exclude = Item->Item.MutualExclude;
  265.  
  266.                             // Is the current item a submenu item?
  267.  
  268.                         if(SUBNUM(Item->MenuCode) == NOSUB)
  269.                             IsSub = FALSE;
  270.                         else
  271.                             IsSub = TRUE;
  272.  
  273.                             // Walk the item list back to the first list entry
  274.                             // in this menu/submenu
  275.  
  276.                         for(Node = Item ; Node->Node.mln_Pred ; Node = (ItemNode *)Node->Node.mln_Pred)
  277.                         {
  278.                                 // Extract the item number
  279.  
  280.                             if(IsSub)
  281.                                 Result = SUBNUM(Node->MenuCode);
  282.                             else
  283.                                 Result = ITEMNUM(Node->MenuCode);
  284.  
  285.                                 // Is this the first item?
  286.  
  287.                             if(!Result)
  288.                             {
  289.                                 LONG i,Mask,Value;
  290.  
  291.                                     // Now build a mask to extract the data
  292.                                     // that should remain constant for all
  293.                                     // items in this list.
  294.  
  295.                                 if(IsSub)
  296.                                     Mask = 0x07FF;    // menu-item + menu
  297.                                 else
  298.                                     Mask = 0x001F;    // menu
  299.  
  300.                                     // This is the constant value
  301.  
  302.                                 Value = Item->MenuCode & Mask;
  303.  
  304.                                     // Now we walk down the list
  305.  
  306.                                 for(i = 0 ; Node->Node.mln_Succ && i < 32 ; i++)
  307.                                 {
  308.                                         // Will this one be affected by the
  309.                                         // mutual exclusion stuff?
  310.  
  311.                                     if(Node != Item && (Node->Item.Flags & CHECKIT) && (Exclude & (1L << i)))
  312.                                         Node->Item.Flags &= ~CHECKED;
  313.  
  314.                                         // Move to the next item
  315.  
  316.                                     Node = (ItemNode *)Node->Node.mln_Succ;
  317.  
  318.                                         // Is this still the same menu/submenu?
  319.  
  320.                                     if((Node->MenuCode & Mask) != Value)
  321.                                         break;
  322.                                 }
  323.  
  324.                                 break;
  325.                             }
  326.                         }
  327.                     }
  328.                 }
  329.  
  330.                 break;
  331.  
  332.                 // Turn menus, submenus and items off or on
  333.  
  334.             case LAMN_Disabled:
  335.  
  336.                 if(Item != NULL || Menu != NULL)
  337.                 {
  338.                     if(Window != NULL)
  339.                     {
  340.                         LONG Code;
  341.  
  342.                         if(Item != NULL)
  343.                             Code = Item->MenuCode;
  344.                         else
  345.                             Code = Menu->MenuCode;
  346.  
  347.                         if(Entry->ti_Data)
  348.                             OffMenu(Window,Code);
  349.                         else
  350.                             OnMenu(Window,Code);
  351.                     }
  352.                     else
  353.                     {
  354.                         UWORD *Flags;
  355.  
  356.                         if(Item)
  357.                             Flags = &Item->Item.Flags;
  358.                         else
  359.                             Flags = &Menu->Menu.Flags;
  360.  
  361.                         if(Entry->ti_Data)
  362.                             *Flags &= ~ITEMENABLED;
  363.                         else
  364.                             *Flags |= ITEMENABLED;
  365.                     }
  366.                 }
  367.  
  368.                 break;
  369.         }
  370.     }
  371.  
  372.         // Reconnect the menu strip if necessary
  373.  
  374.     if(Disconnected)
  375.         ResetMenuStrip(Window,IntuitionMenu);
  376. }
  377.  
  378.  
  379. /*****************************************************************************/
  380.  
  381.  
  382. VOID
  383. LT_MenuControlTags(struct Window *Window,struct Menu *Menu,...)
  384. {
  385.     va_list VarArgs;
  386.  
  387.     va_start(VarArgs,Menu);
  388.     LT_MenuControlTagList(Window,Menu,(struct TagItem *)VarArgs);
  389.     va_end(VarArgs);
  390. }
  391.  
  392. #endif    /* DO_MENUS */
  393.